package com.sharding.order.consumer;

import com.sharding.order.common.enums.OrderOperateType;
import com.sharding.order.common.enums.RequestSource;
import com.sharding.order.domain.dto.OrderItemDetailDto;
import com.sharding.order.domain.entity.OrderInfo;
import com.sharding.order.domain.entity.OrderItemDetail;
import com.sharding.order.domain.message.OrderSyncMessage;
import com.sharding.order.domain.vo.OrderDetailVO;
import com.sharding.order.repository.MerchantOrderRepository;
import com.sharding.order.repository.UserOrderRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
@RocketMQMessageListener(
        consumerGroup = "${order.sync.consumer.group}",
        topic = "${order.topic}"
)
public class OrderSyncConsumer implements RocketMQListener<OrderSyncMessage> {
    @Autowired
    private MerchantOrderRepository merchantOrderRepository;
    @Autowired
    private UserOrderRepository userOrderRepository;

    @Override
    public void onMessage(OrderSyncMessage orderSyncMessage) {
        log.info("received message，start processing,orderNo:[{}],message:[{}]", orderSyncMessage.getOrderNo(), orderSyncMessage);
        //1.check请求来源
        if (Objects.isNull(orderSyncMessage.getRequestSource())) {
            log.error("requestSource can not be empty，orderNo:[{}]", orderSyncMessage.getOrderNo());
            return;
        }

        //2.获取订单源数据
        OrderDetailVO orderDetail = getOrderDetail(orderSyncMessage.getOrderNo(), orderSyncMessage.getRequestSource());

        //3.如果订单为空，打印日志并抛出异常，从而等待rocketMQ下次重试
        if (Objects.isNull(orderDetail)) {
            //打印错误日志
            log.error("orderDetail not exist,orderNo:[{}]", orderSyncMessage.getOrderNo());
            //抛出异常，等待rocketMQ下次重试
            throw new NullPointerException("orderDetail is null,orderNo:[{}]" + orderSyncMessage.getOrderNo());
        }

        //4.获取要处理的目标源
        RequestSource target = RequestSource.C.equals(orderSyncMessage.getRequestSource()) ? RequestSource.B : RequestSource.C;

        //5.同步订单数据的处理,即异构一份订单数据到目标源 或 同步订单状态到目标源
        if (OrderOperateType.add.equals(orderSyncMessage.getOrderOperateType())) {
            //异构一份订单数据到目标源
            syncOrderInfo(orderSyncMessage, orderDetail, target);
        } else if (OrderOperateType.updateOrderStatus.equals(orderSyncMessage.getOrderOperateType())) {
            //同步订单状态到目标源
            updateOrderStatus(orderDetail.getOrderNo(), orderDetail.getOrderStatus(), target);
        }
    }

    /**
     * 异构一份订单数据到目标源
     */
    private void syncOrderInfo(OrderSyncMessage orderSyncMessage, OrderDetailVO orderDetail, RequestSource target) {
        //1.幂等处理，目标订单存在则跳过
        OrderDetailVO targetOrder = getOrderDetail(orderSyncMessage.getOrderNo(), target);
        if (Objects.nonNull(targetOrder)) {
            log.info("targetOrder existed,orderNo:[{}]", orderSyncMessage.getOrderNo());
            return;
        }
        //2.同步订单信息到目标源
        syncOrderInfo(orderDetail, target);
    }

    /**
     * 同步订单信息到目标源
     */
    private void syncOrderInfo(OrderDetailVO orderDetail, RequestSource target) {
        //1.拷贝数据 orderDetail -> orderInfo
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderDetail, orderInfo);

        //2.转换类型 OrderItemDetailDto -> OrderItemDetail
        List<OrderItemDetail> orderItemDetailList = convertOrderItemDetails(orderDetail.getOrderItemDetails());

        //3.异构订单到商家,目前只有从C端下单，异构到B端的业务
        if (RequestSource.B.equals(target)) {
            //异构订单到商家
            merchantOrderRepository.syncOrderInfo(orderInfo, orderItemDetailList);
        }
    }

    /**
     * 获取订单详情
     */
    private OrderDetailVO getOrderDetail(String orderNo, RequestSource requestSource) {
        if (RequestSource.C.equals(requestSource)) {
            return userOrderRepository.getOrderDetail(orderNo);
        } else if (RequestSource.B.equals(requestSource)) {
            return merchantOrderRepository.getOrderDetail(orderNo);
        }
        return null;
    }

    /**
     * 同步订单状态到目标源
     */
    private void updateOrderStatus(String orderNo, Integer orderStatus, RequestSource requestSource) {
        if (RequestSource.C.equals(requestSource)) {
            userOrderRepository.updateStatus(orderNo, orderStatus);
        } else if (RequestSource.B.equals(requestSource)) {
            merchantOrderRepository.updateStatus(orderNo, orderStatus);
        }
    }

    /**
     * 将OrderItemDetailDto类型 转换为 OrderItemDetail类型
     */
    private List<OrderItemDetail> convertOrderItemDetails(List<OrderItemDetailDto> orderItemDetailDtos) {
        List<OrderItemDetail> orderItemDetailList = new ArrayList<>();
        for (OrderItemDetailDto itemDetail : orderItemDetailDtos) {
            OrderItemDetail orderItemDetail = new OrderItemDetail();
            BeanUtils.copyProperties(itemDetail, orderItemDetail);
            orderItemDetailList.add(orderItemDetail);
        }
        return orderItemDetailList;
    }
}